package org.terramagnet.workflow.dynamic.workflow;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.FloatNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.terramagnet.workflow.dynamic.Work;
import org.terramagnet.workflow.dynamic.Workflow;
import org.terramagnet.workflow.dynamic.WorkflowProcess;
import org.terramagnet.workflow.dynamic.databinding.DataType;
import org.terramagnet.workflow.dynamic.databinding.DataTypeBuilder;
import org.terramagnet.workflow.dynamic.databinding.Field;
import org.terramagnet.workflow.dynamic.databinding.type.FloatType;
import org.terramagnet.workflow.dynamic.definition.WorkflowDef;
import org.terramagnet.workflow.dynamic.factory.WorkFactory;

/**
 * 使用Tree模式封装工作流.
 *
 * @author terrason
 */
public class TreeWorkflow implements Workflow {

    public TreeWorkflow(WorkflowDef workflowDef, WorkFactory workFactory) {
        name = workflowDef.getName();
        description = workflowDef.getDescription();

        for (Map.Entry<String, JsonNode> entrySet : workflowDef.getInput().entrySet()) {
            String fieldName = entrySet.getKey();
            JsonNode fieldValue = entrySet.getValue();
            if (StringUtils.isBlank(fieldName)) {
                throw new IllegalArgumentException("输入字段名不能为空");
            }
        }
    }
    /**
     * 流程名称.
     */
    private String name;
    /**
     * 流程说明.
     */
    private String description;

    /**
     * 输入.
     */
    private Collection<Field> inputs;

    /**
     * 输出.
     */
    private Collection<Field> outputs;

    /**
     * 所有工作节点.
     */
    private Map<String, Work> works;

    @Override
    public WorkflowProcess process(JsonNode context) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public String description() {
        return description;
    }

    @Override
    public Collection<Field> inputs() {
        return inputs;
    }

    @Override
    public Collection<Field> outputs() {
        return outputs;
    }

    @Override
    public int size() {
        return works.size();
    }

    @Override
    public boolean isEmpty() {
        return works.isEmpty();
    }

    /**
     * 根据字段定义生成字段实例.
     * @param fieldName 字段名
     * @param fieldDef 字段定义
     * @return 字段实例
     * @throws IllegalArgumentException 不合法的字段定义
     */
    public static Field parseField(String fieldName, JsonNode fieldDef) throws IllegalArgumentException {
        Field field = new Field();
        field.setName(fieldName);

        DataType type = null;
        JsonNode valueNode = fieldDef;
        if (fieldDef.isObject()) {
            valueNode = fieldDef.path("value");
            field.setLabel(fieldDef.path("label").asText(fieldName));
            field.setDescription(fieldDef.path("description").asText(fieldName));
            String typeDef = fieldDef.path("type").asText();
            if (StringUtils.isNotBlank(typeDef)) {
                type = DataTypeBuilder.init(typeDef);
            }
        }
        if (type == null) {
            if (valueNode.isFloat()) {
                type = DataTypeBuilder.createFloatType();
            } else if (valueNode.isDouble()) {
                type = DataTypeBuilder.createDoubleType();
            } else if (valueNode.isInt() || valueNode.isShort()) {
                type = DataTypeBuilder.createIntegerType();
            } else if (valueNode.isLong()) {
                type = DataTypeBuilder.createLongType();
            } else if (valueNode.isBoolean()) {
                type = DataTypeBuilder.createBooleanType();
            } else if (valueNode.isTextual()) {
                type = DataTypeBuilder.createStringType();
            } else {
                throw new IllegalArgumentException("未知的数据类型：" + valueNode.toString());
            }
        }
        field.setType(type);
        field.setValue(type.parse(valueNode.asText()));
        return field;
    }

}
